package com.tonann.web.api;

import com.tonann.app.domain.*;
import com.tonann.app.dto.AppDeviceDto;
import com.tonann.app.mapper.AppSensorRecordDayMapper;
import com.tonann.app.mapper.AppSensorRecordHourMapper;
import com.tonann.app.mapper.AppSensorRecordMonthMapper;
import com.tonann.app.service.IAppDeviceService;
import com.tonann.app.service.IAppFaultService;
import com.tonann.app.service.IAppProjectService;
import com.tonann.app.service.IAppSensorService;
import com.tonann.common.constant.CacheConstants;
import com.tonann.common.constant.Constants;
import com.tonann.common.core.domain.AjaxResult;
import com.tonann.common.core.domain.model.LoginBody;
import com.tonann.common.utils.bean.BeanUtils;
import com.tonann.framework.web.service.SysLoginService;
import com.tonann.web.vo.AppDeviceVO;
import com.tonann.web.vo.SensorAppVO;
import io.swagger.annotations.Api;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.ZoneOffset;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Api("项目数据接口")
@RestController
@RequestMapping("/project/api")
public class ProjectApi {

    @Autowired
    private IAppProjectService projectService;

    @Autowired
    private SysLoginService loginService;
    @Resource
    private IAppDeviceService deviceService;

    @Resource
    private IAppSensorService sensorService;

    @Resource
    private RedisTemplate redisTemplate;

    @Resource
    private IAppFaultService faultService;

    @Resource
    private AppSensorRecordHourMapper recordHourMapper;
    @Resource
    private AppSensorRecordDayMapper recordDayMapper;
    @Resource
    private AppSensorRecordMonthMapper recordMonthMapper;

    /**
     * 获取token方法
     *
     * @param loginBody 登录信息
     * @return 结果
     */
    @PostMapping("/token")
    public AjaxResult getToken(@RequestBody LoginBody loginBody) {
        AjaxResult ajax = AjaxResult.success();
        // 生成令牌
        String token = loginService.getToken(loginBody.getUsername(), loginBody.getPassword());
        ajax.put(Constants.TOKEN, token);
        return ajax;
    }

    @GetMapping("/device/list")
    public AjaxResult getProjectDeviceList(@RequestParam(value = "projectCode", required = false) String projectCode) {
        if (projectCode != null) {
            AppProject project = projectService.selectAppProjectByProjectCode(projectCode);
            if (project != null) {
                AppDevice appDevice = new AppDevice();
                appDevice.setProjectId(project.getProjectId());
                List<AppDevice> deviceList = deviceService.selectAppDeviceAll(appDevice);
                List<AppDeviceDto> dtoList = new ArrayList<>();
                for (AppDevice device : deviceList) {
                    AppDeviceDto dto = new AppDeviceDto();
                    BeanUtils.copyProperties(device, dto);
                    if (appDevice.getIsException() == null) {
                        dto.setIsException("0");
                    }
                    if (appDevice.getIsRunning() == null) {
                        try {
                            String isRunning = (String) redisTemplate.opsForValue().get("device:deviceId:isOnline" + appDevice.getDeviceId());
                            if (isRunning == null) {
                                dto.setIsRunning("1");
                            } else {
                                dto.setIsRunning(isRunning);
                            }
                        } catch (Exception ignored) {
                        }
                    }
                    if (appDevice.getIsRunning() == null) {
                        dto.setIsRunning("1");
                    }
                    dtoList.add(dto);
                }
                return AjaxResult.success(dtoList);
            } else {
                return AjaxResult.error("项目不存在");
            }
        }
        return AjaxResult.error("项目编号为空");
    }

    @GetMapping("/device/detail")
    public AjaxResult getProjectDeviceDetail(@RequestParam(value = "deviceCode", required = false) String deviceCode) {
        if (deviceCode != null) {
            AppDevice appDevice = deviceService.selectAppDeviceByDeviceCode(deviceCode);
            if (appDevice != null) {
                AppDeviceVO vo = new AppDeviceVO();
                List<AppSensor> sensorList = sensorService.selectAppSensorAllListByDeviceIdForApp(appDevice.getDeviceId());
                BeanUtils.copyProperties(appDevice, vo);
                if (appDevice.getIsException() == null) {
                    vo.setIsException("0");
                }
                if (appDevice.getIsRunning() == null) {
                    try {
                        String isRunning = (String) redisTemplate.opsForValue().get("device:deviceId:isOnline" + appDevice.getDeviceId());
                        if (isRunning == null) {
                            vo.setIsRunning("1");
                        } else {
                            vo.setIsRunning(isRunning);
                        }
                    } catch (Exception ignored) {
                    }
                }
                if (appDevice.getIsRunning() == null) {
                    vo.setIsRunning("1");
                }
                List<SensorAppVO> sensorAppVOList = new ArrayList<>();
                if (!sensorList.isEmpty()) {
                    for (AppSensor sensor : sensorList) {
                        String s = null;
                        Object object = redisTemplate.opsForValue().get(CacheConstants.APP_SENSOR_VALUE_KEY + sensor.getDeviceId() + ":sensorId:" + sensor.getSensorId());
                        if (object != null) {
                            if (object instanceof String) {
                                s = object.toString();
                            }
                            if (object instanceof BigDecimal) {
                                s = ((BigDecimal) object).toString();
                            }
                        }
                        if (sensor.getUnit() != null && sensor.getUnit().contains("开关量") && s != null) {
                            sensor.setValue(String.valueOf(new BigDecimal(s).intValue()));
                        } else if (sensor.getUnit() != null && sensor.getUnit().contains("枚举型") && s != null) {
                            List<AppSensorMultiValued> valuedList = sensor.getSensorMultiValuedList();
                            if (valuedList != null && !valuedList.isEmpty()) {
                                String value = String.valueOf(new BigDecimal(s).intValue());
                                for (AppSensorMultiValued valued : valuedList) {
                                    if (valued.getValue().equals(value)) {
                                        sensor.setValue(valued.getMeaning());
                                        break;
                                    }
                                }
                            } else {
                                sensor.setValue(s);
                            }
                        } else {
                            sensor.setValue(s);
                        }
                        SensorAppVO sensorAppVO = getSensorAppVO(sensor);
//                      BeanUtils.copyProperties(sensor,sensorAppVO);
                        sensorAppVOList.add(sensorAppVO);
                    }
                }
                vo.setSensorList(sensorAppVOList);
                return AjaxResult.success(vo);
            } else {
                return AjaxResult.error("设备不存在");
            }
        }
        return AjaxResult.error("设备编号为空");
    }

    private SensorAppVO getSensorAppVO(AppSensor sensor) {
        SensorAppVO vo = new SensorAppVO();
        vo.setSensorId(sensor.getSensorId());
        vo.setSensorCode(sensor.getSensorCode());
        vo.setSensorName(sensor.getSensorName());
        vo.setSensorType(sensor.getSensorType());
        vo.setValue(sensor.getValue());
        vo.setUnit(sensor.getUnit());
        vo.setIsDisplay(sensor.getIsDisplay());
        vo.setIsEnergy(sensor.getIsEnergy());
        vo.setIsLight(sensor.getIsLight());
        vo.setIsExhaust(sensor.getIsExhaust());
        vo.setIsHeight(sensor.getIsHeight());
        vo.setIsOn(sensor.getIsOn());
        vo.setIsMute(sensor.getIsMute());
        vo.setIsForce(sensor.getIsForce());
        vo.setIsFresh(sensor.getIsFresh());
        vo.setIsBeing(sensor.getIsBeing());
        vo.setWorkMode(sensor.getWorkMode());
        vo.setIsAutoDoor(sensor.getIsAutoDoor());
        vo.setFaultRule(sensor.getFaultRule());
        vo.setValueDesc(sensor.getValueDesc());
        vo.setTypeDesc(sensor.getTypeDesc());
        vo.setAlarming(sensor.getAlarming());
        return vo;
    }

    @GetMapping("/device/alarm")//获取设备告警
    public AjaxResult getDeviceAlarm(@RequestParam(value = "deviceCode", required = false) String deviceCode) {
        if (deviceCode != null) {
            AppDevice appDevice = deviceService.selectAppDeviceByDeviceCode(deviceCode);
            if (appDevice != null) {
                AppFault fault = new AppFault();
                fault.setDeviceId(appDevice.getDeviceId());
                List<AppFault> faultList = faultService.selectAppFaultList(fault);
                return AjaxResult.success(faultList);
            } else {
                return AjaxResult.error("设备不存在");
            }
        }
        return AjaxResult.error("设备编号为空");
    }

    //获取传感器按照小时的数值
    @GetMapping("/sensor/hour")
    public AjaxResult getSensorHour(@RequestParam(value = "sensorId", required = false) String sensorId, @RequestParam(value = "startTime", required = false) String startTime, @RequestParam(value = "endTime", required = false) String endTime) {
        if (sensorId != null) {
            AppSensorRecordHour appSensorRecord = new AppSensorRecordHour();
            appSensorRecord.setSensorId(Long.valueOf(sensorId));
            Map<String, Object> map = new HashMap<>();
            if (startTime != null) {
                if (dateTimeValidator(startTime)) {
                    map.put("beginTime", startTime);
                } else {
                    return AjaxResult.error("日期格式错误");
                }
            }
            if (endTime != null) {
                if (dateTimeValidator(endTime)) {
                    map.put("endTime", endTime);
                } else {
                    return AjaxResult.error("日期格式错误");
                }
            }
            appSensorRecord.setParams(map);
            List<AppSensorRecordHour> hourList = recordHourMapper.selectAppSensorRecordHourList(appSensorRecord);
            hourList = hourList.stream().sorted(Comparator.comparing(item -> item.getCreateTime().toEpochSecond(ZoneOffset.of("+8")))).collect(Collectors.toList());
            return AjaxResult.success(hourList);
        }
        return AjaxResult.error("传感器Id为空");
    }

    //获取传感器按照日的数值
    @GetMapping("/sensor/day")
    public AjaxResult getSensorDay(@RequestParam(value = "sensorId", required = false) String sensorId, @RequestParam(value = "startTime", required = false) String startTime, @RequestParam(value = "endTime", required = false) String endTime) {
        if (sensorId != null) {
            AppSensorRecordDay appSensorRecord = new AppSensorRecordDay();
            appSensorRecord.setSensorId(Long.valueOf(sensorId));
            Map<String, Object> map = new HashMap<>();
            if (startTime != null) {
                if (dateTimeValidator(startTime)) {
                    map.put("beginTime", startTime);
                } else {
                    return AjaxResult.error("日期格式错误");
                }
            }
            if (endTime != null) {
                if (dateTimeValidator(endTime)) {
                    map.put("endTime", endTime);
                } else {
                    return AjaxResult.error("日期格式错误");
                }
            }
            appSensorRecord.setParams(map);
            List<AppSensorRecordDay> dayList = recordDayMapper.selectAppSensorRecordDayList(appSensorRecord);
            dayList = dayList.stream().sorted(Comparator.comparing(item -> item.getCreateTime().toEpochDay())).collect(Collectors.toList());
            return AjaxResult.success(dayList);
        }
        return AjaxResult.error("传感器Id为空");
    }

    //获取传感器按照月的数值
    @GetMapping("/sensor/month")
    public AjaxResult getSensorMonth(@RequestParam(value = "sensorId", required = false) String sensorId, @RequestParam(value = "startTime", required = false) String startTime, @RequestParam(value = "endTime", required = false) String endTime) {
        if (sensorId != null) {
            AppSensorRecordMonth appSensorRecord = new AppSensorRecordMonth();
            appSensorRecord.setSensorId(Long.valueOf(sensorId));
            Map<String, Object> map = new HashMap<>();
            if (startTime != null) {
                if (dateTimeValidator(startTime)) {
                    map.put("beginTime", startTime);
                } else {
                    return AjaxResult.error("日期格式错误");
                }
            }
            if (endTime != null) {
                if (dateTimeValidator(endTime)) {
                    map.put("endTime", endTime);
                } else {
                    return AjaxResult.error("日期格式错误");
                }
            }
            appSensorRecord.setParams(map);
            List<AppSensorRecordMonth> monthList = recordMonthMapper.selectAppSensorRecordMonthList(appSensorRecord);
            monthList = monthList.stream().sorted(Comparator.comparing(item -> item.getCreateTime().toEpochDay())).collect(Collectors.toList());
            return AjaxResult.success(monthList);
        }
        return AjaxResult.error("传感器Id为空");
    }

    private boolean dateTimeValidator(String dateTime) {
        String DATE_TIME_PATTERN = "^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$";
        Pattern pattern = Pattern.compile(DATE_TIME_PATTERN);
        Matcher matcher = pattern.matcher(dateTime);
        return matcher.matches();
    }
}
